/*
    This file is part of Raptor.

    Raptor is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Raptor is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Raptor.  If not, see <http://www.gnu.org/licenses/>.

 */

#ifndef RAPTOR_H
#define RAPTOR_H

#include <QtGui/QMainWindow>
#include <QStandardItemModel>
#include <QWizardPage>
#include <QSystemTrayIcon>
#include <QPointer>
#include <QNetworkProxy>

#include "ui_raptor.h"
#include "functions.h"
#include "downloadModel.h"
#include "xmlFileLoader.h"
#include "xmlUrlContainer.h"
#include "configDialog.h"
#include "clipboardDialog.h"

/*! \class Raptor

    \brief raptor main class, with gui

    This is the GUI class, it handels the user input and generates needed objects.
 */


class Raptor : public QMainWindow
{
    Q_OBJECT

    public:
        enum E_EXCEPTION
        {
            EXCEPTION_UNKNOWN,
            EXCEPTION_DIR,
        };

	/*! \struct S_SETTINGS
	    \brief hoster settigns

	    Contains the hoster settings.
	 */
	struct S_SETTINGS
	{
		int maxDownloads;
//		int maxParts; // noch nicht implementieren
		int downloads;

                S_SETTINGS(int const &_maxDownloads, int const &_downloads) : maxDownloads(_maxDownloads), downloads(_downloads) {}
	};

	/*! \struct S_HOSTER
	    \brief hoster infos

	    Holds the informations about a hoster loaded from an xml file.
	 */
	struct S_HOSTER
	{                
		QString fileName;
		QString host;
                QRegExp regexp; //link only
                QRegExp regexp2; //link in text
		xmlFileLoader::E_MODE mode;

		int maxDownloads;
                bool allowOtherHostnames;


		S_SETTINGS free;
		S_SETTINGS premium;

                S_HOSTER(QString const& hosterFileName, QString const& hosterHost, QRegExp const& hosterRegexp, QRegExp const& hosterRegexp2, int const& hosterMaxDownloads, int const& hosterFreeMaxDownloads, int const& hosterPremiumMaxDownloads, xmlFileLoader::E_MODE const& hosterMode, bool const& _allowOtherHostnames) :
                    fileName(hosterFileName),
                    host(hosterHost),
                    regexp(hosterRegexp),
                    regexp2(hosterRegexp2),
                    mode(hosterMode),
                    maxDownloads(hosterMaxDownloads),
                    allowOtherHostnames(_allowOtherHostnames),
                    free(hosterFreeMaxDownloads, 0),
                    premium(hosterPremiumMaxDownloads, 0)
                    { }
	};

	struct S_INFOS
	{
		int progress;
		int state;
		double speed;

		uint fileSize;
		uint downloaded;

		int timeLeft;
		QDateTime downloadStart;
	};

	struct S_PROXY
	{
		QString host;
		uint port;
		QNetworkProxy::ProxyType type;
		QString user;
		QString pass;
	};

        struct S_FOLDERS
        {
            public:
                QDir raptor;
                QDir download;
                QDir captcha;
                QDir hoster;
                QDir container;

                S_FOLDERS():nameRaptor(QDir::currentPath()), nameDownload(QDir::currentPath() + QDir::separator() + "downloads"), nameCaptcha("captcha"), nameHoster("hoster"), nameContainer("urlContainer") {}
                S_FOLDERS(QString const &_raptor, QString const &_download, QString const &_captcha, QString const &_hoster, QString const &_container): nameRaptor(_raptor), nameDownload(_download), nameCaptcha(_captcha), nameHoster(_hoster), nameContainer(_container) {}

                bool setDirs(QString const &_raptor, QString const &_download)
                {
                    nameRaptor = _raptor;
                    nameDownload = _download;

                    return setDirs();
                }

                bool setDirs(QString const &_raptor, QString const &_download, QString const &_captcha, QString const &_hoster, QString const &_container)
                {
                    nameRaptor = _raptor;
                    nameDownload = _download;
                    nameCaptcha = _captcha;
                    nameHoster = _hoster;
                    nameContainer =_container;

                    return setDirs();
                }

                bool setDirs()
                {
                    try
                    {
                        raptor = createDir(nameRaptor, true);
                        QDir::setCurrent(nameRaptor);

                        download = createDir(nameDownload, true);

                        captcha = createDir(nameCaptcha);
                        hoster = createDir(nameHoster);
                        container = createDir(nameContainer);

                        return true;
                    } catch ( int e )
                    {
                        if(e == EXCEPTION_DIR)
                            return false;
                        else
                        {
                            qDebug() << tr("Error: Unknown");
                            throw EXCEPTION_UNKNOWN;
                        }
                    }
                }

                QDir createDir(QString dir, bool absolute=false)
                {
                    if(absolute)
                    {                        
                        QDir tmpDir = QDir::root();
                        if(!tmpDir.exists(dir))
                        {
                            if(tmpDir.mkpath(dir))
                            {
                                tmpDir = QDir(dir);

                                if(tmpDir.isReadable())
                                {
                                    return tmpDir;
                                } else
                                {
                                    qDebug() << tr("Error: Can't read folder: %1").arg(dir);
                                    throw EXCEPTION_DIR;
                                }
                            } else
                            {
                                qDebug() << tr("Error: Can't create folder: %1").arg(dir);
                                throw EXCEPTION_DIR;
                            }
                        } else
                        {
                            tmpDir = QDir(dir);
                            if(tmpDir.isReadable())
                            {
                                return tmpDir;
                            } else
                            {
                                qDebug() << tr("Error: Can't read folder: %1").arg(dir);
                                throw EXCEPTION_DIR;
                            }
                        }
                    } else
                    {
                        if(!raptor.exists(dir))
                            if(!raptor.mkdir(dir))
                            {
                                qDebug() << tr("Error: Can't create folder: %1").arg(dir);
                                throw EXCEPTION_DIR;
                            }
                        
                        QDir tmpDir(raptor.path() + QDir::separator() + dir);
                        if(tmpDir.isReadable())
                        {
                           return tmpDir;
                        } else
                        {
                            qDebug() << tr("Error: Can't read folder: %1").arg(dir);
                            throw EXCEPTION_DIR;
                        }
                    }
                }

            private:
                QString nameRaptor;
                QString nameDownload;
                QString nameCaptcha;
                QString nameHoster;
                QString nameContainer;
        };

	int maxDownloads;
	QList<S_HOSTER*> hosterList;

        S_PROXY proxy;
        S_FOLDERS folders;


        Raptor(QWidget *parent = 0);
        Raptor(S_PROXY _proxy, QString const &folderRaptor, QString const &folderDownload);//int argc, char *argv[]);
        ~Raptor();

        QString getDownloadCollumsWidth();
        void setDownloadCollumsWidth(const QString &width);

        QString getHistoryCollumsWidth();
        void setHistoryCollumsWidth(const QString &width);

        void addWhenReady(QString const& folder, QString const& url);

        void doHosterLogin(const QString hoster, const QString user, const QString pass);

        QMap<QString, QPair<Qt::CheckState, bool> > clipboardLinks;

    signals:

        void needToShow();
            void hosterLoginFinished(const bool error);

    private:

        Ui::RapTorClass ui;

        QMap<int, QPointer<xmlFileLoader> > fileLoader;
        QList<QStringList*> logStrings;

        QMap<QString, QString> waitingDls;

        bool dontSaveDl;
        bool silentAddDl;

        QPointer<clipboardDialog> clipboardDlg;

        bool urlContainerIsOpen;
        xmlUrlContainer urlContainer;

        QString tmpFolderName;

        QPointer<QTimer> timerFileList;
        QPointer<QClipboard> clipboard;

        QPointer<FDownloadModel> modelDownloads;
        QPointer<QStandardItemModel> modelHistory;

        QPointer<QSystemTrayIcon> trayIcon;
        QPointer<QMenu> trayMenu;
        QPointer<QAction> trayActionQuit;
        QPointer<QAction> trayActionShow;
        QPointer<QAction> trayActionHide;

        QPointer<QMenu> downloadRightClickMenu;
        QPointer<QMenu> historyRightClickMenu;

        int activeLog;

        void addInfo(QString str);

        void dlChanged();
        void loadDls();
        void saveDls();

        QPixmap getPixmapByState(const int &state);

        int startLoginFileLoader(const QString &hoster, const QString &user, const QString &pass);
        int startGetSizeFileLoader(const QString &link, const int &logId);
        int startFileLoader(const QString &link, const QString &folder, const QString &file, const int &logId);

        QString getFirstSelectedHosterName();
        QString getFirstSelectedFolderName();

        void writeFileLog(const int &id, const QString &text);

        //QWizardPage *createPageSelectFile();
        //QWizardPage *createPageShowFiles();

        enum modifyAction
        {
            ACTION_START,
            ACTION_PAUSE,
        };

        void modifyItems(const modifyAction &action);

        int getDownloadCount();

        void startFolder(QStandardItem * folder);
        void startDownload(QStandardItem * folder, int row);

        void pauseFolder(QStandardItem * folder);
        void pauseDownload(QStandardItem * folder, int row);

        void deleteDownload(QStandardItem * folder, int row);

        void setSize(const int &logId, const uint &downloaded, const uint &size);

        void addFinishedDownload(const QString &name, const QString &link, const uint &size);

        bool addUrl(const QString &folder, const QUrl &url, const int &state=xmlFileLoader::STATE_STALLED, const uint downloaded=0, const uint size=0);
        bool addUrl(const QString &folder, const QString &url, const int &state=xmlFileLoader::STATE_STALLED, const uint downloaded=0, const uint size=0);

        void setProxy();
        void setProxy(S_PROXY const &_proxy);

        //////////xml file loader, aber hier alles neu
        void loadHosterXml(); //laed alle hoster aus ./hoster/
        void reloadCurrentDlCount();
        int getHosterIdByUrl(const QString &url); //gibt id in hosterList zurueck fuer url - hoster

        bool getLoaderInfos(const int &id, S_INFOS &infos);
        int getNewFileLoader();
        void deleteFileLoader(const int &id);

        void reloadSettings();

        QMap<QString, bool> getAllLinksFromText(QString const& text);
        ////////////////////////////

    private slots:

	void on_actionAddFolder_triggered();
	void on_actionAddFile_triggered();
	void on_actionAddLink_triggered();
	void on_actionStart_triggered();
	void on_actionPause_triggered();
	void on_actionDelete_triggered();
	void on_actionRemoveFinished_triggered();
	void on_actionMoveUp_triggered();
	void on_actionMoveDown_triggered();
	void on_actionPreferences_triggered();

	void on_treeViewDownloads_clicked(const QModelIndex & index);
	void on_treeViewDownloads_customContextMenuRequested(const QPoint & point);
	void on_treeViewHistory_customContextMenuRequested(const QPoint & point);

	void slot_openFolder();

	void slot_timerFileList_timeout();
	void slot_app_aboutToQuit();

	void slot_appShow();
	void slot_appHide();
	void slot_systemTray_activated(QSystemTrayIcon::ActivationReason reason);

	void slot_performClose();

	//xmlFileLoader
	void slot_xmlFileLoader_loginFinished(const int id, const bool error);
	void slot_xmlFileLoader_getSizeFinished(const int &id, const bool &error);
	void slot_xmlFileLoader_downloadFinished(const int &id, const bool &error);
	void slot_xmlFileLoader_statusMsg(const int &logId, const QString &text);
	void slot_xmlFileLoader_changeMode(const int &id, const xmlFileLoader::E_MODE mode);
	//

	void slot_clipboard_dataChanged();

    public slots:
	void handleMessage(const QString& message);
};

#endif // RapTor_H
